/*
// Licensed to Julian Hyde under one or more contributor license
// agreements. See the NOTICE file distributed with this work for
// additional information regarding copyright ownership.
//
// Julian Hyde licenses this file to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
 */
package org.olap4j;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

/**
 * Result of executing an OLAP Statement.
 * 
 * <p>
 * A <code>CellSet</code> consists of a set of (typically two) axes, each populated with a sequence of members, and a
 * collection of cells at the intersection of these axes.
 * 
 * <p>
 * <b>Cell ordinals and coordinates</b>
 * </p>
 * 
 * <p>
 * There are two ways to identify a particular cell: ordinal and coordinates. Suppose that there are <code>p</code>
 * axes, and each axis <code>k</code> (<code>k</code> between 0 and <code>p - 1</code>) has <code>U<sub>k</sub></code>
 * positions. There are <code>U</code> = <code>U<sub>0</sub> * ... * U<sub>p - 1</sub></code> cells in total. Then:
 * <ul>
 * <li>A cell's <code>ordinal</code> is an integer between 0 and <code>U - 1</code>.</li>
 * <li>A cell's <code>coordinates</code> are a list of <code>p</code> integers, indicating the cell's position on each
 * axis. Each integer is between 0 and <code>U<sub>p</sub>-1</code>.</li>
 * </ul>
 * 
 * <p>
 * The ordinal number of a cell whose tuple ordinals are
 * <code>(S<sub>0</sub>, S<sub>1</sub>, ... S<sub>p-1</sub>)</code> is <blockquote> <code>
 * &#931;<sub>i=0</sub><sup>p-1</sup> S<sub>i</sub> . E<sub>i</sub>
 * </code> where <code>E<sub>0</sub> = 1</code> and <code>
 * E<sub>i</sub> = &#928;<sub>i=0</sub><sup>p-1</sup> U<sub>k</sub>
 * </code> </blockquote>
 * </p>
 * 
 * @author jhyde
 * @since Aug 22, 2006
 */
public interface CellSet extends ResultSet, OlapWrapper {

	/**
	 * Retrieves the <code>OlapStatement</code> object that produced this <code>CellSet</code> object. If the result set
	 * was generated some other way, such as by a {@link org.olap4j.OlapDatabaseMetaData} method, this method may return
	 * <code>null</code>.
	 * 
	 * @return the <code>OlapStatment</code> object that produced this <code>CellSet</code> object or <code>null</code>
	 *         if the cell set was produced some other way
	 * 
	 * @exception SQLException
	 *                if a database access error occurs or this method is called on a closed cell set
	 */
	OlapStatement getStatement() throws SQLException;

	/**
	 * Retrieves the description of this <code>CellSet</code>'s axes and cells.
	 * 
	 * @return the description of this <code>CellSet</code>'s axes and cells
	 * @exception OlapException
	 *                if a database access error occurs
	 */
	CellSetMetaData getMetaData() throws OlapException;

	/**
	 * Retrieves a list of CellSetAxis objects containing the result.
	 * 
	 * <p>
	 * The list contains axes according to their ordinal: 0 is the columns axis, 1 the rows axis, and so forth.
	 * 
	 * @return list of CellSetAxis objects containing the result
	 * 
	 * @see #getFilterAxis()
	 */
	List<CellSetAxis> getAxes();

	/**
	 * Retrieves the CellSetAxis representing the filter axis.
	 * 
	 * <p>
	 * If the query has a WHERE clause, the contains the members returned by that expression. Most query authors write a
	 * WHERE clause so that it evaluates to just one member or tuple. The members in this tuple (or the sole member),
	 * are referred to as the 'slicer context' of the query. The tuple contains only members of hierarchies explicitly
	 * mentioned in the WHERE expression; the slicer context of every hierarchy in the query's cube is implicitly the
	 * default member of that hierarchy.
	 * 
	 * <p>
	 * While not typical, note that a query's WHERE clause may also evaluate to zero or more than one tuples.
	 * 
	 * <p>
	 * If the query has no WHERE clause, the filter axis has a single position, but the position has no members.
	 * 
	 * <p>
	 * The filter axis is not included in the {@link #getAxes()} collection.
	 * 
	 * @return the filter axis
	 */
	CellSetAxis getFilterAxis();

	/**
	 * Returns the Cell at a given set of coordinates.
	 * 
	 * @param coordinates
	 *            List of 0-based coordinates of the cell
	 * 
	 * @return Cell
	 * 
	 * @throws IndexOutOfBoundsException
	 *             if coordinates are outside CellSet bounds
	 */
	Cell getCell(List<Integer> coordinates);

	/**
	 * Returns the Cell at an ordinal.
	 * 
	 * <p>
	 * Equivalent to
	 * 
	 * <blockquote><code>
	 * getCell(ordinalToCoordinates(ordinal))
	 * </code></blockquote>
	 * 
	 * @param ordinal
	 *            0-based ordinal of the cell
	 * 
	 * @return Cell
	 * 
	 * @throws IndexOutOfBoundsException
	 *             if ordinal lies outside CellSet bounds
	 */
	Cell getCell(int ordinal);

	/**
	 * Returns the Cell at the intersection of a set of axis positions.
	 * 
	 * <p>
	 * Equivalent to
	 * 
	 * <blockquote>
	 * 
	 * <pre>
	 * <code>
	 * getCell(
	 *     Arrays.asList(
	 *         positions[0].ordinal(),
	 *         positions[1].ordinal() [, ...]))
	 * </code>
	 * </pre>
	 * 
	 * </blockquote>
	 * 
	 * @param positions
	 *            Array of positions
	 * 
	 * @return Cell
	 * 
	 * @throws IllegalArgumentException
	 *             if positions does not have the same number of members as the cell set has axes
	 * 
	 * @throws IndexOutOfBoundsException
	 *             if positions lie outside CellSet bounds
	 */
	Cell getCell(Position... positions);

	/**
	 * Converts a cell ordinal to a list of cell coordinates.
	 * 
	 * @param ordinal
	 *            Cell ordinal
	 * @return Cell coordinates
	 */
	List<Integer> ordinalToCoordinates(int ordinal);

	/**
	 * Converts a list of cell coordinates to a cell ordinal.
	 * 
	 * @param coordinates
	 *            Cell coordinates
	 * @return Cell ordinal
	 */
	int coordinatesToOrdinal(List<Integer> coordinates);

}

// End CellSet.java
